package com.authine.cloudpivot.ext.controller;

import com.alibaba.fastjson.JSON;
import com.authine.cloudpivot.engine.api.model.application.*;
import com.authine.cloudpivot.engine.api.model.runtime.UserFavoritesModel;
import com.authine.cloudpivot.engine.api.model.system.AdminModel;
import com.authine.cloudpivot.engine.enums.type.AdminType;
import com.authine.cloudpivot.engine.enums.type.BizObjectType;
import com.authine.cloudpivot.engine.enums.type.NodeType;
import com.authine.cloudpivot.ext.service.CloudSqlService;
import com.authine.cloudpivot.web.api.controller.runtime.AppRuntimeController;
import com.authine.cloudpivot.web.api.handler.CustomizedOrigin;
import com.authine.cloudpivot.web.api.util.VoUtils;
import com.authine.cloudpivot.web.api.view.ResponseResult;
import com.authine.cloudpivot.web.api.view.app.AppGroupVO;
import com.authine.cloudpivot.web.api.view.app.AppPackageVO;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RList;
import org.redisson.api.RSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

@Api(tags = {"运行时::应用"})
@RestController
@RequestMapping("/api/runtime/app")
@Slf4j
@CustomizedOrigin(level = 1)
public class CustomAppRuntimeController extends AppRuntimeController {


    @Autowired
    Redisson redisson;
    final String hideAppGroupCodesKey = "hideAppGroupCodes";
    final String hideAppCodesKey = "hideAppCodes";
    static boolean isFirst = true;

    @Autowired
    CloudSqlService sqlService;

    public Set<String> getHideSetting(String key){

        if(isFirst){
            refreshHideSetting();
            isFirst=false;
        }
        Set<String> set = redisson.getSet(key);
        if (set == null) {
            return  Collections.emptySet();
        }
        return set;
    }

    private void toRefreshHideSetting(){
        try {
            String tableName = getBizObjectFacade().getTableName("appModeHideSetting");
            StringBuilder sql = new StringBuilder("select appGroupCodes,appCodes from ").append(tableName).append("  limit 1");

            Map<String, Object> map = sqlService.getMap(sql.toString());

            String appGroupCodes = MapUtils.getString(map, "appGroupCodes", "");
            String appCodes = MapUtils.getString(map, "appCodes", "");


            if (StringUtils.isNotEmpty(appGroupCodes)) {
                RSet<String> hideGroupSet = redisson.getSet(hideAppGroupCodesKey);
                hideGroupSet.addAll(Arrays.asList(appGroupCodes.split(",")));
            }

            if(StringUtils.isNotEmpty(appCodes)){
                RSet<String> hideAppSet = redisson.getSet(hideAppCodesKey);
                hideAppSet.addAll(Arrays.asList(appCodes.split(",")));
            }
        } catch (Exception e) {
            log.info("刷新应用隐藏配置失败",e);
        }
    }

    @RequestMapping("refreshHideSetting")
    public void refreshHideSetting(){
        isFirst = true;
        toRefreshHideSetting();
    }






    @GetMapping({"/list_apps"})
    public ResponseResult<List<AppPackageVO>> listApps(@RequestParam Boolean isMobile) {
        String currentUserId = this.getUserId();
        List<AppPackageModel> appPackages = this.getAppManagementFacade().getAppPackagesByUserId2(currentUserId, isMobile);
        List<AppPackageVO> appPackageList = this.getApps(isMobile, appPackages);

        List<AdminModel> userAdminList = getUserAdminList(getUserId());
        boolean flag = true;
        if (!userAdminList.isEmpty()) {
            List<AdminModel> collect = userAdminList.stream().filter(a -> a.getAdminType() == AdminType.SYS_MNG || a.getAdminType() == AdminType.ADMIN).collect(Collectors.toList());
            if(collect.size()>0){
                //管理员不用过滤
                flag = false;
            }

        }
        if (flag) {
            Set<String> hideSetting = getHideSetting(hideAppCodesKey);
            appPackageList =  appPackageList.stream().filter(a->  !hideSetting.contains(a.getCode())).collect(Collectors.toList());
        }

        return this.getOkResponseResult(appPackageList, "获取数据成功");
    }





    @ApiImplicitParam(
            name = "isMobile",
            value = "是否移动端",
            required = true,
            dataType = "Boolean",
            paramType = "query"
    )
    @GetMapping({"/list_apps_group"})
    public ResponseResult<List<AppGroupVO>> listAppsGroup(@RequestParam Boolean isMobile) {
        List<AppGroupPresentModel> groupPresentModels = this.getAppManagementFacade().getAppGroupsByUserId(this.getUserId(), isMobile);
        List<AppGroupVO> appGroupVOS = Lists.newArrayListWithExpectedSize(CollectionUtils.size(groupPresentModels));
        if (CollectionUtils.isNotEmpty(groupPresentModels)) {

            List<AdminModel> userAdminList = getUserAdminList(getUserId());
            boolean flag = true;
            if (!userAdminList.isEmpty()) {
                List<AdminModel> collect = userAdminList.stream().filter(a -> a.getAdminType() == AdminType.SYS_MNG || a.getAdminType() == AdminType.ADMIN).collect(Collectors.toList());
                if(collect.size()>0){
                    //管理员不用过滤
                    flag = false;
                }
            }
            Set<String> appHides =  getHideSetting(hideAppCodesKey);
            if (flag) {
                Set<String> hideSetting = getHideSetting(hideAppGroupCodesKey);
                groupPresentModels =  groupPresentModels.stream().filter(a->  !hideSetting.contains(a.getCode())).collect(Collectors.toList());
            }



            Iterator var4 = groupPresentModels.iterator();

            while(var4.hasNext()) {
                AppGroupPresentModel groupPresentModel = (AppGroupPresentModel)var4.next();
                AppGroupVO appGroupVO = new AppGroupVO(groupPresentModel);
                if(CollectionUtils.isNotEmpty(groupPresentModel.getPresentModels())){
                    if(flag){
                        List<AppPresentModel> collect = groupPresentModel.getPresentModels().stream().filter(a -> !appHides.contains(a.getCode())).collect(Collectors.toList());
                        appGroupVO.addAllChildren(VoUtils.toVo(collect, AppPackageVO.class));
                    }else{
                        appGroupVO.addAllChildren(VoUtils.toVo(groupPresentModel.getPresentModels(), AppPackageVO.class));
                    }
                }
                appGroupVOS.add(appGroupVO);
            }

            appGroupVOS.sort(Comparator.comparing((AppGroupVO appGroupVOx) -> {
                return appGroupVOx.getModel().getSortKey();
            }, Comparator.nullsLast(Integer::compareTo)).thenComparing((appGroupVOx) -> {
                return appGroupVOx.getModel().getCreatedTime();
            }));

        }

        return this.getOkResponseResult(appGroupVOS, "获取数据成功");
    }

    private List<AppPackageVO> getApps(boolean isMobile, List<AppPackageModel> appPackages) {
        long start = System.currentTimeMillis();
        List<AppPackageVO> appPackageList = null;
        long start2 = System.currentTimeMillis();
        log.debug("从引擎获取应用耗时 = {} ms", System.currentTimeMillis() - start2);
        List<UserFavoritesModel> favoritesModels = this.getUserSettingFacade().getUserFavorites(this.getUserId(), BizObjectType.APP_PACKAGE);
        Set<String> favoritesAppCodes = Sets.newHashSet();
        if (CollectionUtils.isNotEmpty(favoritesModels)) {
            favoritesAppCodes = (Set)favoritesModels.stream().map(UserFavoritesModel::getBizObjectKey).collect(Collectors.toSet());
        }

        appPackageList = new ArrayList();
        long start3 = System.currentTimeMillis();
        if (CollectionUtils.isNotEmpty(appPackages)) {
            if (log.isDebugEnabled()) {
                log.debug("获取到的应用数量:{}", appPackages.size());
            }

            if (log.isTraceEnabled()) {
                log.trace("获取到的应用为:{}", JSON.toJSONString(appPackages));
            }

            appPackages = (List)appPackages.stream().sorted(Comparator.comparingInt(AppPackageModel::getSortKey)).collect(Collectors.toList());

            AppPackageVO appPackageVO;
            for(Iterator var12 = appPackages.iterator(); var12.hasNext(); appPackageList.add(appPackageVO)) {
                AppPackageModel appPackageModel = (AppPackageModel)var12.next();
                appPackageVO = new AppPackageVO(appPackageModel);
                appPackageVO.setFavorites(((Set)favoritesAppCodes).contains(appPackageVO.getCode()));
                if (isMobile && CollectionUtils.isEmpty(appPackageList)) {
                    List<AppFunctionModel> children = this.getAppManagementFacade().getAppFunctionsByPackCode(appPackageModel.getCode());
                    if (CollectionUtils.isNotEmpty(children)) {
                        appPackageVO.setChildren((List)children.stream().filter((t) -> {
                            return t.getType().equals(NodeType.BizModel);
                        }).collect(Collectors.toList()));
                    }
                }
            }
        }

        log.info("appPackageList.add = {} ms.", System.currentTimeMillis() - start3);
        log.info("getOkResponseResult db = {} ms.", System.currentTimeMillis() - start);
        return appPackageList;
    }

}
